TransWikia.com

How to define an environment inside which any undefined environment is "defined"?

TeX - LaTeX Asked on July 27, 2021

I need to define an environment inside which I can simply do begin{some string}some stuffend{some string} with arbitrary strings, and have it process these as environments (which output e.g. textbf{some string:} somestuff). The environments should also accept an optional parameter that modifies their behavior.

Preexisting environments like enumerate or itemize should still work inside my environment.

I can achieve most of this with the following code:

makeatletter
defifEqString#1#2{defcsa{#1}defcsb{#2}ifxcsacsb }
defifUnDefinedCs#1{expandafter ifxcsname#1endcsnamerelax}
letold@begin=begin
defnew@begin{ifx[next expandafternewXX@begin else expandafternewX@begin fi}
defnewX@begin#1{ifUnDefinedCs{#1}newZ@begin{#1}elseold@begin{#1} fi}
defnewZ@begin#1{head@font{#1}parnewenvironment{#1}{lethead@font=textit}{relax}old@begin{#1}}
defnewXX@begin[#1]#2{ifEqString{#1}{plain}--else{#1}fi {#2}parnewenvironment{#2}{lethead@font=textit}{relax}old@begin{#2}}
newenvironment{myenvironment}{begingroup%
lethead@font=textbf
defbegin{futureletnextnew@begin}
}{endgroup}
makeatother

However, this breaks preexisting environments like tabular that require parameters to be given. Is there a better way to code this that doesn’t break these?

One Answer

I think you're going to have to do some heavy lifting here. A simple patching of begin won't do the job because begin has to be able to read optional and required arguments on occasion. You're much better off just declaring a custom environment for your needs. You can even keep your typing concise by giving it a nice short name, e.g., (assuming xparse is available):

NewDocumentEnvironment{||}{ m o }{%
   IfNoValueTF{#2}{%
      No optional argument
   }%
   {%
     Optional argument #2
   }%
   textbf{#1:}}%
   {} % We don't need to do anything at the end

begin{||}{some string} some stuff end{||}

But if you don't want to do that, declare the command that will handle your special environment:

NewDocumentCommand{UndeclaredEnvironment}{ m o }{...}

This will take the name of the undeclared environment as its first required argument and then an optional argument and you can define it like we did the environment above.

Now comes surgery time. Before we go any further, let me emphasize that this is a bad idea. texdoc source2e will give you the annotated source code for LaTeX. The definition for begin appears on page 473 in the D ltmiscen.dtx section:

DeclareRobustCommand*begin[1]{%
  UseHook{env/#1/before}%
  @ifundefined{#1}%
    {defreserved@a{@latex@error{Environment #1 undefined}@eha}}% ❶
    {defreserved@a{def@currenvir{#1}%
        edef@currenvline{on@line}%
        @execute@begin@hook{#1}%
        csname #1endcsname}}%
  @ignorefalse
  begingroup@endpefalsereserved@a}

The line we're interested in is the one I've marked with ❶. You'll want to copy the above to a new command, say, BadIdeaBegin (with makeatletter active) and change that line to read:

    {defreserved@a{def@currenvir{#1}%
        edef@currenvline{on@line}%
        @execute@begin@hook{#1}%
        UndeclaredEnvironment{#1}}}%

Then you can have your environment be

newenvironment{VeryBadIdea}{letbeginBadIdeaBegin}{}

And things will work the way you think you want them to work.

Correct answer by Don Hosek on July 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP