1

I would like to create an environment that, provided with either center, left or right creates a center, flushleft, or flushright environment.

My current code is the following:

\newenvironment{withalignment}[1]{%
    \ifthenelse{\equal{#1}{center}}{\begin{center}}{%
        \ifthenelse{\equal{#1}{left}}{\begin{flushleft}}{%
            \ifthenelse{\equal{#1}{right}}{\begin{flushright}}{}%
        }%
    }%
}{%
    \ifthenelse{\equal{#1}{center}}{\end{center}}{%
        \ifthenelse{\equal{#1}{left}}{\end{flushleft}}{%
            \ifthenelse{\equal{#1}{right}}{\end{flushright}}{}%
        }%
    }%
}%

But:

  1. It does not seem to work
  2. The recursive \ifthenelse is rather ugly and if a better solution was available, that would be great

How to make it work in an elegant way?

2
  • 1
    "it does not work" is not a good problem description. Always make a small but complete example that demonstrates the problem and can be used for a test. Commented Sep 18, 2023 at 11:01
  • The end part of a \newenvironment doesn't have access to the arguments #1, …. You need to save them in a macro or use the new \NewDocumentEnvironment from xparse. Instead of the ifthenelsing just use #1 directly as the environment name. For that, define a flushcenter environment that's a copy of center. (I'd use a key-value system or just c, r and l as arguments that can be \ifed.) Commented Sep 18, 2023 at 12:26

2 Answers 2

3

Here's with expl3; you can use l, c or r besides left, center or right.

\documentclass{article}
\usepackage{lipsum} % for mock text

\ExplSyntaxOn

\NewDocumentEnvironment{withalignment}{m}
 {
  \begin{\vincent_alignment:n { #1 }}
 }
 {
  \end{\vincent_alignment:n { #1 }}
 }

\cs_new:Nn \vincent_alignment:n
 {
  \str_case:nn { #1 }
   {
    {c}{center}
    {center}{center}
    {l}{flushleft}
    {left}{flushleft}
    {r}{flushright}
    {right}{flushright}
   }
 }
\ExplSyntaxOff

\begin{document}

\section{Long arguments}

\begin{withalignment}{left}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{center}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{right}
\lipsum[1][1-4]
\end{withalignment}

\section{Short arguments}

\begin{withalignment}{l}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{c}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{r}
\lipsum[1][1-4]
\end{withalignment}

\end{document}

enter image description here

With error management:

\documentclass{article}
\usepackage{lipsum} % for mock text

\ExplSyntaxOn

\NewDocumentEnvironment{withalignment}{m}
 {
  \cs_if_exist:cTF { \vincent_alignment:n { #1 } }
   {% the environment exists
    \begin{\vincent_alignment:n { #1 }}
   }
   {
    \msg_error:nnn { vincent/alignment } { bad-argument } { #1 }
   }
 }
 {
  \cs_if_exist:cT { \vincent_alignment:n { #1 } }
   {
    \end{\vincent_alignment:n { #1 }}
   }
 }

\msg_new:nnnn { vincent/alignment } { bad-argument }
 {
  Wrong~argument~'#1'~to~'withalignment'
 }
 {
  The~allowed~arguments~are~l,~c,~r,~left,~center,~right
 }

\cs_new:Nn \vincent_alignment:n
 {
  \str_case:nn { #1 }
   {
    {c}{center}
    {center}{center}
    {l}{flushleft}
    {left}{flushleft}
    {r}{flushright}
    {right}{flushright}
   }
 }

\ExplSyntaxOff

\begin{document}

\begin{withalignment}{xyzzz}
\end{withalignment}

\section{Long arguments}

\begin{withalignment}{left}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{center}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{right}
\lipsum[1][1-4]
\end{withalignment}

\section{Short arguments}

\begin{withalignment}{l}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{c}
\lipsum[1][1-4]
\end{withalignment}

\begin{withalignment}{r}
\lipsum[1][1-4]
\end{withalignment}

\end{document}

The wrong argument would make TeX issue

! Package vincent/alignment Error: Wrong argument 'xyzzz' to 'withalignment'

For immediate help type H <return>.
 ...

l.48 \begin{withalignment}{xyzzz}

? h

The allowed arguments are l, c, r, left, center, right
2
  • There seems to be a problem when my alignment is passed through a macro/command. How to modify the code to handle this case?
    – Vincent
    Commented Sep 19, 2023 at 15:29
  • @Vincent Replace \str_case:nn with \str_case_e:nn
    – egreg
    Commented Sep 19, 2023 at 19:37
2

Still not very elegant with all the \ifs, but it works.

\documentclass{article}
\newcommand*{\alignment}{}
\newenvironment{withalignment}[1]{%
    \renewcommand*{\alignment}{#1}
    \if\alignment c
        \begin{center}%
    \else\if\alignment l
        \begin{flushleft}%
    \else\if\alignment r
        \begin{flushright}%
    \fi\fi\fi%
}{%
    \if\alignment c
        \end{center}%
    \else\if\alignment l
        \end{flushleft}%
    \else\if\alignment r
        \end{flushright}%
    \fi\fi\fi%
}
\begin{document}
This is text outside of \texttt{withalignment}.

\begin{withalignment}{c}
This is text in \texttt{withalignment} with parameter \texttt{c}.
\end{withalignment}

\begin{withalignment}{l}
This is text in \texttt{withalignment} with parameter \texttt{l}.
\end{withalignment}

\begin{withalignment}{r}
This is text in \texttt{withalignment} with parameter \texttt{r}.
\end{withalignment}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .