关于自定义环境结合条件判断的一个问题

发布于 2022-04-03 21:12:51

我现有如下代码,自定义了weizil,weizic,weizir三个环境,如何把这个三个环境合成一个新定义环境,然后给出选项l,c,r,根据l,c,r的不同选择对应的环境?

\documentclass{ctexart}
\newenvironment{weizil}[1][]
{\begin{flushleft}
\begin{minipage}{#1\textwidth}

}{\end{minipage}\end{flushleft}}
\newenvironment{weizic}[1][]
{\begin{center}
\begin{minipage}{#1\textwidth}

}{\end{minipage}\end{center}}

\newenvironment{weizir}[1][]
{\begin{flushright}
\begin{minipage}{#1\textwidth}

}{\end{minipage}\end{flushright}}

\begin{document}
\begin{weizil}[0.5]
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizil}
\begin{weizic}[0.6]
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizic}
\begin{weizir}[0.55]
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizir}
\end{document}

查看更多

关注者
0
被浏览
727
如果您有什么不同意见,您是对的,我是错的。
这家伙很懒,什么也没写!

第一个参数是 [],第二个是 {}

\documentclass{ctexart}
\usepackage{xparse}
\newenvironment{weizil}[1][]
{\begin{flushleft}
\begin{minipage}{#1\textwidth}
}{\end{minipage}\end{flushleft}}

\newenvironment{weizic}[1][]
{\begin{center}
\begin{minipage}{#1\textwidth}
}{\end{minipage}\end{center}}

\newenvironment{weizir}[1][]
{\begin{flushright}
\begin{minipage}{#1\textwidth}
}{\end{minipage}\end{flushright}}

\ExplSyntaxOn
\NewDocumentEnvironment { test } { O{c} m }
  {
    \tl_if_eq:NNTF { #1 } { l }
      {
        \begin{weizil}[#2]
      }
      {
        \tl_if_eq:NNTF { #1 } { c }
        {
          \begin{weizic}[#2]
        }
        {
          \begin{weizir}[#2]
        }
      }
  }
  {
    \tl_if_eq:NNTF { #1 } { l }
    {
      \end{weizil}
    }
    {
      \tl_if_eq:NNTF { #1 } { c }
      {
        \end{weizic}
      }
      {
        \end{weizir}
      }
    }
  }
\ExplSyntaxOff


\begin{document}
\begin{test}[c]{0.5}
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{test}
\end{document}
2 个回答
雾月
雾月 2022-04-04
这家伙很懒,什么也没写!

这里再给出几种方法。

由于使用 \begin{<env>} 时,LaTeX 将会(在该命令执行的最末尾)展开 \csname <env>\endcsname
使用 \end{<env>},将会展开 \csname end<env>\endcsname,我们可以在 \<env> 中定义 \end<env>

\newcommand\weizi[2][c]{%
  \strcase{#1}
    {{c}{\def\endweizi{\end{minipage}\end{center}}%
         \begin{center}}
     {l}{\def\endweizi{\end{minipage}\end{flushleft}}%
         \begin{flushleft}}
     {r}{\def\endweizi{\end{minipage}\end{flushright}}%
         \begin{flushright}}}
     {}
     {\def\endweizi{\end{minipage}\end{center}}%
      \begin{center}}%
  \begin{minipage}{#2\textwidth}}

也就是根据相应的可选参数,定义对应的 \end<env>。这里的 \strcase 对应于 LaTeX3 的 \str_case_e:nnTF

% \strcase := LaTeX3 \str_case_e:nnTF
\expandafter\let\expandafter\strcase\csname str_case_e:nnTF\endcsname

使用方式为:

\begin{weizi}[c]{0.5}
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

这样的定义是可以嵌套使用的,因为每一对 \begin ... \end 都放在一个组中。

另一种方式涉及到 centerflushleftflushright 环境的实现。这三个环境都是使用 trivlist 环境实现的,它们的 \end<...> 都是 \endtrivlist。(具体细节可以在 source2e.pdf 中找到。)

因此实际上可以写得更加简单,不论 clr\endweizi 都可以定义为 \def\endweizi{\endminipage\endtrivlist}

包装成一个环境就是:

\newenvironment{weizi}[2][c]
  {\strcase{#1}
      {{c}{\center}
        {l}{\flushleft}
        {r}{\flushright}}
      {}
      {\center}
    \minipage{#2\textwidth}}
  {\endminipage\endtrivlist}

使用方式是完全相同的。

另一个就是使用 cmdxparse),我们可以方便的使用可选参数:

\DeclareDocumentEnvironment {weizi} { !D(){} !O{c} !D(){#1} }
  {\strcase{#2}
      {{c}{\center}
        {l}{\flushleft}
        {r}{\flushright}}
      {}
      {\center}
    \minipage{#3\textwidth}}
  {\endminipage\endtrivlist}

这样,

\begin{weizi}
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}(0.5)
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}[c]
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}[c](0.5)
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}(0.5)[c]
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

都是可以的。

汇总:

\documentclass{ctexart}

% \strcase := LaTeX3 \str_case_e:nnTF
\expandafter\let\expandafter\strcase\csname str_case_e:nnTF\endcsname

\begin{document}

\newenvironment{weizi}[2][c]
  {\strcase{#1}
      {{c}{\center}
        {l}{\flushleft}
        {r}{\flushright}}
      {}
      {\center}
    \minipage{#2\textwidth}}
  {\endminipage\endtrivlist}

\begin{weizi}[c]{0.5}
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\renewcommand\weizi[2][c]{%
  \strcase{#1}
    {{c}{\def\endweizi{\end{minipage}\end{center}}%
         \begin{center}}
     {l}{\def\endweizi{\end{minipage}\end{flushleft}}%
         \begin{flushleft}}
     {r}{\def\endweizi{\end{minipage}\end{flushright}}%
         \begin{flushright}}}
     {}
     {\def\endweizi{\end{minipage}\end{center}}%
      \begin{center}}%
  \begin{minipage}{#2\textwidth}}

\begin{weizi}[c]{0.5}
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}


\DeclareDocumentEnvironment {weizi} { !D(){} !O{c} !D(){#1} }
  {\strcase{#2}
      {{c}{\center}
        {l}{\flushleft}
        {r}{\flushright}}
      {}
      {\center}
    \minipage{#3\textwidth}}
  {\endminipage\endtrivlist}

\begin{weizi}
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}(0.5)
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}[c]
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}[c](0.5)
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\begin{weizi}(0.5)[c]
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
  文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
\end{weizi}

\end{document}

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览