5

Consider the following:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn \NewDocumentCommand{\demo}{m}{ \str_case:nnF{#1} { {a} {Run case 1\ % Actually super long code } {b} {Run case 1\ % Actually super long code }

} { % False code } } \ExplSyntaxOff

\begin{document} \demo{a} \demo{b} \end{document}

Is there any way I can define the "b" case without having to copy all of my "actually super long code"?

Clément
  • 5,591
  • 3
    Note that there is no need to load xparse with a sufficiently new TeX distribution. – Jasper Habicht Aug 08 '23 at 17:30
  • 3
    Why not define a variable that does "Run case 1"? – gusbrs Aug 08 '23 at 17:31
  • 1
    @gusbrs Because my "actually super long code" is actually some further \IfValueTF that performs test on optional arguments to \demo and that sound prone to error and too complicated :-) – Clément Aug 08 '23 at 17:46
  • 2
    @Clément Then a function, and pass said arguments... – gusbrs Aug 08 '23 at 17:52
  • @gusbrs Good thinking, and that's what's done in some of the answers below. I actually ended up … calling the function itself with the "other" argument, and that works perfectly well for my particular case. – Clément Aug 09 '23 at 14:46
  • 1
    @Clément Well, it is more convincing when you hear it from @ egreg. ;-) – gusbrs Aug 09 '23 at 14:50

4 Answers4

6

Use a function that provides the very long code. It's recommended to use \New(Expandable)DocumentCommand just to parse the arguments and then to pass control to a function.

Whenever you have long code that's part of other code, it's best to make auxiliary functions.

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\demo}{m} { \clement_code_cases:n { #1 } }

\cs_new:Nn \clement_code_cases:n { \str_case:nnF{#1} { {a} { __clement_code_superlong: } {b} { __clement_code_superlong: } {c} { Simpler~code } } { False~code } }

\cs_new:Nn __clement_code_superlong: { Some~very~long~code }

\ExplSyntaxOff

\begin{document}

\demo{a}

\demo{b}

\demo{c}

\demo{d}

\end{document}

enter image description here

Remember to use \cs_new_protected:(...) when the code contains unexpandable functions.

egreg
  • 1,121,712
  • Thanks a lot for your very clean solution. It is elegant and extremely flexible. For my particular use case, I found something that I consider simpler, but your solution will most likely be useful in the future! – Clément Aug 09 '23 at 14:45
5

Change b to a before testing

\documentclass{article}

\ExplSyntaxOn \cs_generate_variant:Nn\str_case:nnF{e} \NewDocumentCommand{\demo}{m}{ \str_case:enF{ \str_case:enF{#1}{ {b}{a} } {#1} } { {a} {Run case 1\par % Actually super long code }

} { % False code } } \ExplSyntaxOff

\begin{document} \demo{a} \demo{b} \end{document}

David Carlisle
  • 757,742
  • Thanks a lot for your very ingenious solution, that I really like. I manufactured something that I consider even simpler, but I really enjoyed your creativity and the simplicity of your solution! – Clément Aug 09 '23 at 14:44
4

You could try regular expressions, such as in the following example (note that the order of the two first arguments is different between \regex_match_case:nnF and \str_case:nnF):

\documentclass{article}

\ExplSyntaxOn \NewDocumentCommand{\demo}{m}{ \regex_match_case:nnF{ {\A[ab]\Z} {Run case 1\ % Actually super long code } }{#1}{ % false code } } \ExplSyntaxOff

\begin{document} \demo{a} \demo{b} \end{document}

  • Ok, strange syntax but that could work. Maybe a bit of an overkill since my two strings are simple, but ok. Where is the \A[ab]\Z syntax explained? I'm not familiar with it (my strings are 2 characters long). – Clément Aug 08 '23 at 17:47
  • @Clément It is not pure regex syntax, but ^[ab]$ would also work. The expl3 commands and the LaTeX3-style regex syntax are explained in the LaTeX3 Interfaces PDF. For regex syntax in general search the internet for "regular expressions". – Jasper Habicht Aug 08 '23 at 17:59
  • 1
    \A[ab]\Z means: \A (or ^) = start of string; \Z (or $) = end of string; [ab] = one of a or b. If you need two-character strings, you could also use (ab|cd|ef) which would mean one of ab or cd or ef (add as many pipes as needed). – Jasper Habicht Aug 08 '23 at 18:01
  • Thanks a lot for your clarifications and very ingenious solution. I found something that I consider simpler, but I'm sure your answer will be useful to other -- as of me, I learned about those regular expressions thanks to you! – Clément Aug 09 '23 at 14:43
1

The simplest solution that I found was to call the macro again with the other argument, as follows:

\documentclass{article}

\ExplSyntaxOn \NewDocumentCommand{\demo}{m}{ \str_case:nnF{#1} { {a} {Run case 1\ % Actually super long code } {b} { \demo{a} }

}
{
    % False code
}

} \ExplSyntaxOff

\begin{document} \demo{a} \demo{b} \end{document}

It may be restricted to my particular use case, but it works fine.

Clément
  • 5,591