In the package that I have been developing, I use the \perfectunary
command from the Perfectcut package to get auto-growing brackets that increase in size depending on the number of nested brackets inside them. On the whole, this works extremely well and generally gives me results I am delighted with (occasionally the larger brackets look silly, but it usually noticeably enhances legibility). The only problem I have come across is that anything defined with perfectunary
does not seem to allow line breaks at all. Most of the time that isn't a problem, but sometimes there will be something using nested brackets that ends up simply too long for one line, and the only option to deal with I know of is to use line breaks.
Looking at the source for Perfectcut, it seemingly implements versions of \left
and \right
, which I guess are the reason for the inability to break across lines. I'm afraid that the LaTeX code for the package is a bit beyond me, however. I'll also point out one thing that I have seen in its documentation, about reimplementing the sizes of delimiters (in section 5). It sounds like that could be a useful behaviour to retain, though I am in no way desperate to keep using Perfectcut if there is a handy alternative (for that matter, I'm also not above borrowing the bits of it that are relevant for me and discarding the rest, if that makes sense).
My question is, is there any way that I can replicate the auto-growing effect where it depends upon the nesting level, but which also permits manually inserted line breaks as needed? Automatic line breaking would be wonderful, but I imagine that's much too complex. Since the overly long lines are usually something that can be left until almost the last minute, and there are normally not too many of them, a heavily manual process is acceptable.
I have looked around at various delimiter questions on here, such this, this, this and this, but I am afraid that again the answers there are a bit beyond me. My best guess is that the best (or, at least, almost certainly the easiest) solution to my current problem would be to use the \DeclarePairedDelimiter
command from Mathtools, but I'm not quite managing to put the pieces together to achieve what I want.
To give some idea (hopefully) of what I am aiming at, I have prepared the below MWE:
\documentclass[a4paper]{article}
\usepackage{amsmath}
\usepackage{perfectcut}
\usepackage{framed}
\usepackage{changepage}
\makeatletter
\newenvironment{cpruleset}
{\begin{framed}\begin{adjustwidth}{-1.0em}{-1.0em}
\renewcommand{\arraystretch}{1.1}\[\begin{array}{lllllr}}
{\end{array}\]\end{adjustwidth}\end{framed}}
\newcommand{\cprule}[5]{
\refstepcounter{cpsystems@RuleNum}
#1 & #2 & \rightarrow_{#3} & #4 & #5 & \hspace{1.5em}(\thecpsystems@RuleNum)\\
}
\newcommand*{\cpfunc}[2]{
#1\perfectunary{IncreaseHeight}{(}{)}{#2}
}
\newcommand*{\cpfuncms}[2]{
#1\perfectunary{IncreaseHeight}{\{}{\}}{#2}
}
\newcommand*{\cpfuncalt}[2]{
#1(#2)
}
\newcommand*{\cpfuncmsalt}[2]{
#1\{#2\}
}
\newcommand*{\cppromoter}[1]{
& & & & ~ \quad ~ | ~ #1 & \\
}
\newcounter{cpsystems@RuleNum}
\makeatother
\title{MWE}
\author{jcoo092}
\begin{document}
\maketitle
\section{First section}
\begin{cpruleset}
\cprule{s_1}{\cpfunc{v}{\cpfunc{v}{R}Y}}{1}{s_2}{\cpfunc{s}{\cpfunc{r}{R} \; \cpfunc{u}{Y} \; \cpfunc{p}{\cpfunc{h}{R}\cpfunc{p}{\,}}} \; \cpfunc{c}{\lambda}}
\cprule{s_2}{\cpfunc{s}{\cpfunc{r}{R} \; \cpfunc{u}{\,} \; \cpfunc{p}{\cpfunc{h}{F}\cpfunc{p}{P}} \; \cpfunc{c}{C}}}
% \cprule{s_2}{\cpfunc{s}{\cpfunc{r}{R} \; \cpfunc{u}{\,} &&\\& \enskip \; \cpfunc{p}{\cpfunc{h}{F}\cpfunc{p}{P}} \; \cpfunc{c}{C}}}
{+}{s_3}{\cpfunc{z}{\cpfunc{p}{\cpfunc{h}{R} \cpfunc{p}{\cpfunc{h}{F}\cpfunc{p}{P}}}} \; \cpfuncms{c}{W}}
\cppromoter{\cpfunc{e}{\cpfunc{f}{F} \; \cpfunc{t}{T} \; \cpfunc{c}{W}}}
\cprule{s_2}{}{+}{s_2}
{\cpfunc{s}{\cpfunc{r}{R} \; \cpfunc{u}{Z} \; \cpfunc{p}{\cpfunc{h}{T} \cpfunc{p}{\cpfunc{h}{F} \cpfunc{p}{P}}} \; \cpfunc{c}{CW}}}
\cppromoter{\cpfunc{s}{\cpfunc{r}{R} \; \cpfuncms{u}{\cpfunc{v}{T}Z} \; \cpfunc{p}{\cpfunc{h}{F} \cpfunc{p}{P}} \; \cpfunc{c}{C}}}
\cppromoter{\cpfunc{e}{\cpfunc{f}{F} \; \cpfunc{t}{T} \; \cpfunc{c}{W}}}
\cprule{s_2}{\cpfunc{s}{\_}}{+}{s_2}{}
\cprule{s_3}{}{1}{s_4}{\cpfunc{p'}{P} \quad \cpfunc{c'}{1D}}
\cppromoter{\cpfunc{z}{\cpfunc{p}{P \; \cpfunc{c}{1D}}}}
\end{cpruleset}
\newpage
\begin{cpruleset}
\cprule{s_1}{\cpfuncalt{v}{\cpfuncalt{v}{R}Y}}{1}{s_2}{\cpfuncalt{s}{\cpfuncalt{r}{R} \; \cpfuncalt{u}{Y} \; \cpfuncalt{p}{\cpfuncalt{h}{R}\cpfuncalt{p}{\,}}} \; \cpfuncalt{c}{\lambda}}
\cprule{s_2}{\cpfuncalt{s}{\cpfuncalt{r}{R} \; \cpfuncalt{u}{\,} &&\\& \enskip \; \cpfuncalt{p}{\cpfuncalt{h}{F}\cpfuncalt{p}{P}} \; \cpfuncalt{c}{C}}}
{+}{s_3}{\cpfuncalt{z}{\cpfuncalt{p}{\cpfuncalt{h}{R} \cpfuncalt{p}{\cpfuncalt{h}{F}\cpfuncalt{p}{P}}}} \; \cpfuncmsalt{c}{W}}
\cppromoter{\cpfuncalt{e}{\cpfuncalt{f}{F} \; \cpfuncalt{t}{T} \; \cpfuncalt{c}{W}}}
\cprule{s_2}{}{+}{s_2}
{\cpfuncalt{s}{\cpfuncalt{r}{R} \; \cpfuncalt{u}{Z} &\\&&&& \enskip \; \cpfuncalt{p}{\cpfuncalt{h}{T} \cpfuncalt{p}{\cpfuncalt{h}{F} \cpfuncalt{p}{P}}} \; \cpfuncalt{c}{CW}}}
\cppromoter{\cpfuncalt{s}{\cpfuncalt{r}{R} \; \cpfuncmsalt{u}{\cpfuncalt{v}{T}Z} &\\&&&& \qquad \enskip \; \cpfuncalt{p}{\cpfuncalt{h}{F} \cpfuncalt{p}{P}} \; \cpfuncalt{c}{C}}}
\cppromoter{\cpfuncalt{e}{\cpfuncalt{f}{F} \; \cpfuncalt{t}{T} \; \cpfuncalt{c}{W}}}
\cprule{s_2}{\cpfuncalt{s}{\_}}{+}{s_2}{}
\cprule{s_3}{}{1}{s_4}{\cpfuncalt{p'}{P} \quad \cpfuncalt{c'}{1D}}
\cppromoter{\cpfuncalt{z}{\cpfuncalt{p}{P \; \cpfuncalt{c}{1D}}}}
\end{cpruleset}
\(\cpfunc{s}{\cpfunc{r}{R} \; \cpfunc{u}{Z} \; \\ \cpfuncms{p}{\cpfunc{h}{T} \cpfunc{p}{\cpfunc{h}{F} \cpfunc{p}{P}}} \; \cpfunc{c}{CW}}\)
\end{document}
The aim is to have the auto-growing behaviour from the first cpruleset
, while also using the line breaks in the second cpruleset
to make everything fit within the page margins. I have included both cases with parentheses and curly braces, to highlight the fact that different types of brackets can be (and are in practice) mixed and matched within a given nested set. In case it makes a difference, in my head I am aiming at an approach where the relevant opening and closing brackets only open or close their own line, rather than growing to wrap every line inside themselves, but if the latter is much easier to accomplish I'm happy with it too.
The newcommand
s are essentially copy-pasted from the .sty file for my package, and then simplified down to the minimum possible, except for cpfuncalt
and cpfuncmsalt
--- I introduced them specifically for the purposes of the MWE. The top cpruleset
is how I would normally set out this sort of thing using Perfectcut, and the bottom cpruleset
is the same as the top one, but with the uses of perfectunary
removed so that I can demonstrate the sort of line breaks I would like to insert.
Both the last line outside the cpruleset
s, and the commented-out line in the top one, are there to demonstrate the problems I experience. The bottom line has a line break command in it that seemingly gets ignored. If I uncomment the commented-out line, and comment out the line above it (which is the same but without a line break), then I get an error that reads:
> ! Misplaced alignment tab character &. <argument> ... \cpfunc {r}{R}
> \; \cpfunc {u}{\,} &
> &\\& \enskip \; \cpfunc {p...
> l.58 ...{h}{F}\cpfunc{p}{P}}}} \; \cpfuncms{c}{W}}
I assume that this occurs because the line break has been ignored, so the extra &s included to make the array line up properly appear to be part of the same line.