使用 perfectcut 在自动增长的嵌套括号内换行?

使用 perfectcut 在自动增长的嵌套括号内换行?

在里面我一直在开发的包,我使用\perfectunary来自Perfectcut 套装获得自动增长的括号,其大小取决于括号内嵌套的括号数量。总的来说,这种方法效果非常好,通常能给我带来满意的结果(有时较大的括号看起来很傻,但通常可以明显提高可读性)。我遇到的唯一问题是,用 定义的任何内容perfectunary似乎都不允许换行。大多数情况下这不是问题,但有时使用嵌套括号会导致一行太长,而我知道的唯一解决方法是使用换行符。

看看Perfectcut 的来源它似乎实现了\left和的版本\right,我猜这就是无法跨行换行的原因。不过,恐怕这个包的 LaTeX 代码有点超出我的理解范围。我还要指出我在其文档中看到的一件事,关于重新实现分隔符的大小(第 5 节)。这听起来像是一种有用的行为,值得保留,尽管如果有方便的替代方案,我并不急于继续使用 Perfectcut(就此而言,我也不介意借用与我相关的部分并丢弃其余部分,如果这有意义的话)。

我的问题是,有什么方法可以复制自动增长的效果吗这取决于嵌套级别,但是还允许根据需要手动插入换行符? 自动换行很棒,但我认为这太复杂了。由于过长的行通常可以留到最后一分钟,而且行数通常不会太多,因此大量手动操作是可以接受的。

我环顾四周分隔符问题在这里,这样的,但我担心那里的答案又有点超出我的理解范围。我最好的猜测是,解决我当前问题的最佳(或至少几乎肯定是最简单的)方法是使用\DeclarePairedDelimiterMathtools 中的命令,但我无法将各个部分组合在一起来实现我想要的结果。

为了(希望)让您了解我的目标,我准备了以下 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}

目的是从第一个开始具有自动增长行为cpruleset,同时在第二个中使用换行符cpruleset使所有内容适合页边距。我在两种情况下都使用了圆括号和花括号,以强调不同类型的括号可以(实际上也是)在给定的嵌套集合中混合和匹配。如果这会产生影响,我脑海中的目标是一种方法,其中相关的开始和结束括号仅打开或关闭它们自己的行,而不是增长以将每一行包装在它们自己内部,但如果后者更容易实现,我也会对此感到满意。

这些newcommands 基本上是从我的包的 .sty 文件,然后将其简化到最低限度,除了cpfuncaltcpfuncmsalt--- 我专门为 MWE 引入了它们。顶部cpruleset是我通常使用 Perfectcut 设置此类内容的方式,底部cpruleset与顶部相同,但perfectunary删除了 的用法,以便我可以演示我想要插入的换行符类型。

s外的最后一行cpruleset和最上面注释掉的行都演示了我遇到的问题。最下面一行有一个换行命令,但似乎被忽略了。如果我取消注释注释掉的行,并注释掉上面的行(相同但没有换行符),那么我会收到一条错误消息:

> ! Misplaced alignment tab character &. <argument> ... \cpfunc {r}{R}
> \; \cpfunc {u}{\,} &
>                                                   &\\& \enskip \; \cpfunc {p...
> l.58 ...{h}{F}\cpfunc{p}{P}}}} \; \cpfuncms{c}{W}}

我认为发生这种情况是因为换行符被忽略了,因此包含的使数组正确排列的额外 &s 看起来像是同一行的一部分。

答案1

发布完这个问题后,我又回去尝试使用 Mathtools 的DeclarePairedDelimiter命令。我最终得到了这个:

\DeclarePairedDelimiter{\cpparens}{\lparen}{\rparen}

\newcommand*{\cpfuncalt}[3][]{
  #2\cpparens[#1]{#3}
}

这导致了 MWE 的修订:

\documentclass{article}

\usepackage{mathtools}
\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)\\
}

\DeclarePairedDelimiter{\cpparens}{\lparen}{\rparen}
\DeclarePairedDelimiter{\cpcurls}{\lbrace}{\rbrace}

\newcommand*{\cpfunc}[2]{
#1\perfectunary{IncreaseHeight}{\lparen}{\rparen}{#2}
}

\newcommand*{\cpfuncms}[2]{
#1\perfectunary{IncreaseHeight}{\lbrace}{\rbrace}{#2}
}

\newcommand*{\cpfuncalt}[3][]{
#2\cpparens[#1]{#3}
}

\newcommand*{\cpfuncmsalt}[3][]{
{#2\cpcurls[#1]{#3}}
}

\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}{\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}{\cpfuncalt[\Big]{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}
        {\cpfuncalt[\bigg]{s}{\cpfunc{r}{R} \; \cpfunc{u}{Z} &\\&&&& \enskip \cpfunc{p}{\cpfunc{h}{T} \cpfunc{p}{\cpfunc{h}{F} \cpfunc{p}{P}}} &\\&&&& \enskip \cpfunc{c}{CW}}}
        \cppromoter{\cpfuncalt[\Big]{s}{\cpfunc{r}{R} \; \cpfuncmsalt[\big]{u}{\cpfunc{v}{T}Z} &\\&&&& \qquad \enskip \cpfuncalt[\big]{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}
    
\(\cpfuncalt[\bigg]{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}

使用这个额外的命令,我能够cpfunc在大多数情况下继续使用 Perfectcut ( ) 定义的命令,并且只用涉及手动调整大小的命令替换一些命令。通常,只有最外面的括号需要换行,所以我通常只需手动调整它们就可以了。

这实现了最低限度我需要的,但我不太喜欢它。我希望实现的改进包括:

  • 使用 Perfectcut 的尺寸测量,而不是 AMSMath 的少量,以避免尺寸之间出现任何不一致。
  • 采用一些自动化的方式来计算嵌套数量并进行适当的设置,以避免可能容易出错的手动过程。
  • 说实话,我怀疑自己是否能有效地利用 Mathtools 提供的资源。我确信有更好/更有效/更有用的方法来定义这些东西,但我对 Mathtools 的理解太有限了,无法发现它。
  • 确保换行符开始缩进至少到其上方封闭术语的其余部分,甚至可能更多一点的方法。现在,我基本上只是手动插入空格来获得相同的效果,但我确信一定有更好的方法(可能是某种phantom空格?)
  • 一种表示括号内的内容已移至另一行的方法。目前,我正在考虑添加一个 U+21B5 或类似的字符,但我正在努力弄清楚如何添加它(不过,这一点可能是一个单独的问题)。
  • 我怀疑,cpfuncalt按照定义,该命令很容易出现奇怪的小错误,而错误报告却没有明确说明。如果能让它更好地帮助用户识别错误的位置和内容就好了,但我不知道该怎么做。

如果有人愿意尝试解决上述任何问题,或以其他方式改进这一点,我将不胜感激。

相关内容