1

Based on this answer, I am trying to define a newcases environment that automatically expands "if" into ", \quad & \text{if }" and expands "otherwise" into ", \quad & \text{otherwise}". My code and the output are included below. As you can see in the output, the result is incorrect with \geq, \\, and \empty rendered literally and fl inserted at each line break in the code.

\documentclass{article}
\usepackage{filecontentsdef}
\usepackage{amsmath}

\ExplSyntaxOn \cs_generate_variant:Nn \tl_replace_all:Nnn {Nx} \NewDocumentEnvironment {newcases} {} { % Use filecontentsdef to store everything until "\endfilecontentsdefmacro" % into a macro named "\l__envcontents_tmp_tl". \filecontentsdefmacro \l__envcontents_tmp_tl } { \endfilecontentsdefmacro \str_set:NV \l__envcontents_tmp_tl \l__envcontents_tmp_tl

\tl_replace_all:Nxn \l__envcontents_tmp_tl
  { \c_space_tl\tl_to_str:n{if} \c_space_tl} % Search
  {, \quad & \text{if~}}                     % Replace
\tl_replace_all:Nxn \l__envcontents_tmp_tl 
  {\tl_to_str:n{otherwise}}       % Search
  {, \quad \text{otherwise}}      % Replace

% Output the result.
\left\{\begin{array}{ll}
\l__envcontents_tmp_tl

\end{array}\right. } \ExplSyntaxOff

\begin{document}

Desired output: \begin{equation} \begin{cases} a, \quad & \text{if } a \geq 0, \ -a, \quad & \text{otherwise}. \end{cases} \end{equation}

Actual output, using newcases environment: \begin{equation} \begin{newcases} a if a \geq 0 \ -a otherwise. \end{newcases} \end{equation}

\end{document}

enter image description here

Paul Wintz
  • 402
  • 2
  • 14
  • I don't see the point in not specifying the & 's. Plus mathtools already provide cases* that plus the second vil in text mode – daleif Aug 16 '23 at 19:31
  • How many if will be used? – projetmbc Aug 16 '23 at 19:36
  • @daleif, I'd like to automatically include the comma before the &, so I'd like to not explicitly write &. The cases* environment looks useful, but I'd still like to define the environment I described, partially as a way of better understand expl3 syntax. – Paul Wintz Aug 16 '23 at 19:47
  • @projetmbc, there may be multiple ifs. – Paul Wintz Aug 16 '23 at 19:47

1 Answers1

1

Solution without additional packages

Use a regex search and replace.

I'd not use newcases for the environment's name, because mathtools has a \newcases command.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\tl_new:N \l__wintz_cases_tl

\NewDocumentEnvironment {autocases} {b} { \tl_set:Nn \l__wintz_cases_tl { #1 } % Search any control sequences immediately followed by "if". % If there is, insert a space between so the subsequent regex works. \regex_replace_all:nnN { (\c{.*}) if } { \1\ if } \l__wintz_cases_tl % Search and replace "<space>if<space>" with ", \quad & \text{if }" \regex_replace_all:nnN { \s+if\s+ } { , \c{quad} &amp; \c{text}{if\ } } \l__wintz_cases_tl % Search and replace "otherwise" with ", \quad & \text{otherwise}" \regex_replace_all:nnN { otherwise } { , \c{quad} &amp; \c{text}{otherwise} } \l__wintz_cases_tl % Output the result. \begin{cases} \tl_use:N \l__wintz_cases_tl \end{cases} }{} \ExplSyntaxOff

\begin{document}

Desired output: \begin{equation} \begin{cases} a, \quad & \text{if } a \geq 0, \ -a, \quad & \text{otherwise}. \end{cases} \end{equation}

Actual output, using autocases environment: \begin{equation} \begin{autocases} a if a \geq 0 \ -a otherwise. \end{autocases} \end{equation}

Actual output, using autocases environment: \begin{equation} \begin{autocases} \infty if a \geq 0 \ \oplus if a < -1 \ 0 otherwise. \end{autocases} \end{equation}

\end{document}

enter image description here

With filecontentsdef (As in the original question)

Caveat. You should also be aware that autocases (or whatever name you prefer) cannot be used in amsmath alignment displays. For an environment that can be used with amsmathalignment displays, use the approach described above.

You want to rescan the string you get.

Don't mix strings with token lists: they're different data types. You also forgot an & and want to use cases, not array.

\documentclass{article}
\usepackage{filecontentsdef}
\usepackage{amsmath}

\ExplSyntaxOn

\str_new:N \l__envcontents_tmp_str \cs_generate_variant:Nn \str_replace_all:Nnn {Nx}

\NewDocumentEnvironment {autocases} {} { % Use filecontentsdef to store everything until "\endfilecontentsdefmacro" % into a string named "\l__envcontents_tmp_str". \filecontentsdefmacro \l__envcontents_tmp_str } { \endfilecontentsdefmacro

\str_replace_all:Nxn \l__envcontents_tmp_str
  { \c_space_tl\tl_to_str:n{if} \c_space_tl} % search
  {, \quad &amp; \text{if~}} % replace
\str_replace_all:Nxn \l__envcontents_tmp_str
  {\tl_to_str:n{otherwise}} % search
  {, \quad &amp; \text{otherwise}} % replace

% Output the result.
\begin{cases}
\tl_rescan:nV {} \l__envcontents_tmp_str
\end{cases}

} \ExplSyntaxOff

\begin{document}

Desired output: \begin{equation} \begin{cases} a, \quad & \textup{if } a \geq 0, \ -a, \quad & \textup{otherwise}. \end{cases} \end{equation}

Actual output, using autocases environment: \begin{equation} \begin{autocases} a if a \geq 0 \ -a otherwise. \end{autocases} \end{equation}

\end{document}

Paul Wintz
  • 402
  • 2
  • 14
egreg
  • 1,121,712
  • Does using the name l__envcontents_tmp_str instead of l__envcontents_tmp_tl change the type? (I think not) Or was filecontentsdefmacro outputting a string the whole time and the variable was just mislabeled? – Paul Wintz Aug 18 '23 at 08:34
  • 1
    @PaulWintz Both are actually macros, but sticking to the naming scheme is helpful in distinguishing between types. With \filecontentsdefmacro you get “verbatim”, that one might consider the same as a string. – egreg Aug 18 '23 at 08:36
  • Got it. Thanks. For the line \c_space_tl\tl_to_str:n{if} \c_space_tl, is that not still mixing strings (l\tl_to_str:n{if}) and token lists (\c_space_tl)? – Paul Wintz Aug 18 '23 at 08:38
  • 1
    @PaulWintz These are subtleties. However, you should read the final “Caveat” I added. – egreg Aug 18 '23 at 08:39
  • I'll keep the caveat in mind. What's the gist for why that doesn't work? – Paul Wintz Aug 18 '23 at 08:43
  • For this particular command, it's not a big deal since I don't put cases into aligned environments often, but it would be nice to know what aspect of this general approach prevents it from working in those aligned environments. – Paul Wintz Aug 18 '23 at 08:45
  • 1
    @PaulWintz You can't gather verbatim in the argument to a command. I'm going to add a version that's free from the problem. – egreg Aug 18 '23 at 08:46
  • if the code before the "if" is a macro without braces, then the output is not formatted right. For example, \begin{autocases} \infty if \gamma > 1. end{autocases} does not work right but \begin{autocases} \infty{} if \gamma > 1. \end{autocases}. Is this something that can fixed by modifying the autocases environment? – Paul Wintz Sep 09 '23 at 01:26
  • 1
    @PaulWintz I added an initial search for “(control sequence) if” to add a space in the middle. – egreg Sep 10 '23 at 08:14