0

I'd like to programmatically create a new \NewDocumentEnvironment environment to create new environments using a simple command (a bit like how one can use\newtheorem to create a new kind of environment).

However, I'm not sure how to do that. Should I use some sort of expandafter, \csname...?

MWE

\documentclass[]{article}
\usepackage{xparse}

%% Environment generic but too verbose to use. (I need the +b) \NewDocumentEnvironment{myenv}{O{}m+b}{ Foo (#1) Bar (#2) Baz (#3) Bise}{}

%% Create a command to create new environment to fix the options of the verbose env. \NewDocumentCommand\newEnv{O{}mm}{ \NewDocumentEnvironment{#1}{O{}+b}{ \begin{myenv}[##1]{#2} ##3 \end{myenv} }{} } %% Use it to create a new environment \newEnv[dolphin]{myDolpinEnv}{I am a dolphin.}

\begin{document}

\begin{myenv}[I'm optional]{I'm mandatory} I'm inside. \end{myenv}

\begin{myDolpinEnv}[blue dolphin] Psiooouu! \end{myDolpinEnv}

\end{document}

tobiasBora
  • 8,684
  • 1
    By the way note that these pseudo-environment cannot contain \verb, and you may want to look into filecontentsdef, but then is loses synctex support. – user202729 Jan 28 '22 at 13:18
  • @user202729 It's funny that you mention verb as I exactly got this same issue ^^ By "pseudo-environment" you mean using +b? Unfortunately, I can't find any solution to avoid them in my use case https://github.com/leo-colisson/proof-at-the-end, and this issue seems quite fundamental (I remember helping someone having similar issues with verb and maybe the answers package`, and the only solution we had we to use typeset verb content outside inside some sort of box and move the box back inside the answer later) . – tobiasBora Jan 28 '22 at 13:25
  • 1
    Learn catcode, capture the environment body verbatim, manipulate as necessary, then use scantokens to reparse it. Or use filecontentsdef, but you still need to learn catcode to use it properly. See e.g. https://tex.stackexchange.com/q/543921/250119 (and linked questions) and my answer https://tex.stackexchange.com/a/622425/250119 for a reference. – user202729 Jan 28 '22 at 13:28
  • @user202729 Thanks. Can your solution deal with synctex? That said, it seems quite a lot of work, and it may produce side effects... I need to see if it's worth implementing it. But in case you are motivated, feel free to send PR ;-) – tobiasBora Jan 28 '22 at 13:38
  • Actually... why capturing the body at all? Just \NewDocumentEnvironment{#1}{O{}+}{ \myenv[##1]{#2} }{ \endmyenv } – user202729 Jan 28 '22 at 13:58
  • Because this is a MWE. In real life I may need to discard the environment and/or write it in another file. – tobiasBora Jan 28 '22 at 13:59
  • Okay, then the general solution requires verbatim capture (mentioned above). synctex (and error-reporting in general) is a general issue that happens regardless, LuaTeX has some functions to manipulate it, but I haven't fully figured out how to use it. – user202729 Jan 28 '22 at 14:30
  • @user202729 Ok thanks! Losing synctex in the environment would be quite problematic (I already kind of lose it when proofs are moved in appendix), but it's good to know that there are alternatives. If at some points you figure out how LuaTex can manipulate synctex, please drop me a message, I'm very interested! – tobiasBora Jan 28 '22 at 19:54
  • 1

1 Answers1

0

Ok, I found the solution, I did some typo in my original environments.

\documentclass[]{article}
\usepackage{xparse}

%% Environment generic but too verbose to use. (I need the +b) \NewDocumentEnvironment{myenv}{O{}m+b}{ Foo (#1) Bar (#2) Baz (#3) Bise}{}

%% Create a command to create new environment to fix the options of the verbose env. \NewDocumentCommand\newEnv{O{}mm}{ \NewDocumentEnvironment{#2}{O{}+b}{ \begin{myenv}[#1,##1]{#3} ##2 \end{myenv} }{} } %% Use it to create a new environment \newEnv[dolphin]{myDolpinEnv}{I am a dolphin.}

\begin{document}

\begin{myenv}[I'm optional]{I'm mandatory} I'm inside. \end{myenv}

\begin{myDolpinEnv}[blue dolphin] Psiooouu! \end{myDolpinEnv}

\end{document}

tobiasBora
  • 8,684
  • 1
    That \expandafter does nothing there (it tries to expand the {, which doesn't expand) – Phelype Oleinik Jan 28 '22 at 13:05
  • 1
    Do you really need the \expandafter? At least in the example I cannot see a difference when I leave it out. And given how \newEnv is used in your examples I cannot see why the \expandafter would be necessary at all (though you would need one more to actually do something exciting). The argument #2 in \newEnv is not something that needs to be expanded. – moewe Jan 28 '22 at 13:06
  • In general I would have thought that since environments are called by environment name (with \begin{<name>}...\end{<name>}) and not as control sequences directly (as in \<name>) you don't need to worry about \expandafter and \csname at all in order to programmatically create new ones. (The \csname...\endcsname is applied by LaTeX for you.) – moewe Jan 28 '22 at 13:11
  • In these cases I guess you also want to learn expl3, then read texdoc interface3. – user202729 Jan 28 '22 at 13:17
  • Indeed, I don't need expandafter, it was just that I made a typo in my original theorems... My bad. – tobiasBora Jan 28 '22 at 13:17
  • Is the insertion of horizontal space intentional? Why do you need myenv at all? Why not just e.g. Foo (#1,##1) Bar (#3) Baz (##2) Bise for the definition? – cfr Feb 18 '24 at 05:20