How to perform a globalrenewenvironment
Clash Royale CLAN TAG#URR8PPP
up vote
5
down vote
favorite
I need to execute a renewenvironment
within a group. Using globalrenewenvironment
is not sufficient.
What changes do I need to make to the DisableMyEnvironment
macro in the MWE below so as to achieve the equivalent of globalrenewenvironment
?
Currently, the MWE yields:
Once this is working as desired, the second line in blue should be in black.
Notes:
- There are two test cases. The default one is within a
foreach
and commenting outdefForeachTestCase
uses a simple group.
References:
globalrenewcommand equivalent of globaldef.
Code:
defForeachTestCase%
documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%
else
begingroup
DisableMyEnvironment
endgroup
fi
medskippar
MyTestTextblack
enddocument
macros environments grouping
 |Â
show 1 more comment
up vote
5
down vote
favorite
I need to execute a renewenvironment
within a group. Using globalrenewenvironment
is not sufficient.
What changes do I need to make to the DisableMyEnvironment
macro in the MWE below so as to achieve the equivalent of globalrenewenvironment
?
Currently, the MWE yields:
Once this is working as desired, the second line in blue should be in black.
Notes:
- There are two test cases. The default one is within a
foreach
and commenting outdefForeachTestCase
uses a simple group.
References:
globalrenewcommand equivalent of globaldef.
Code:
defForeachTestCase%
documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%
else
begingroup
DisableMyEnvironment
endgroup
fi
medskippar
MyTestTextblack
enddocument
macros environments grouping
I don't know your real application, but one option is to useaftergroupDisableMyEnvironment
. I don't know if this will do what you want, though.
â Phelype Oleinik
Aug 28 at 18:47
@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within afpreach
). Will look into it and try to figure it out.
â Peter Grill
Aug 28 at 18:50
I read somewhere that aforeach
does its thing inside two grouping levels, soaftergroupaftergroupaftergroupDisableMyEnvironment
should do. Not the prettiest code there is though :P
â Phelype Oleinik
Aug 28 at 18:52
@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both theenvironement
andendenvironment
separately.
â Peter Grill
Aug 28 at 19:16
It's a bit hacky, but would work:letdefgdefrenewenvironmentMyEnvironment[1]
and it's global!
â Andreas Storvik Strauman
Aug 28 at 19:29
 |Â
show 1 more comment
up vote
5
down vote
favorite
up vote
5
down vote
favorite
I need to execute a renewenvironment
within a group. Using globalrenewenvironment
is not sufficient.
What changes do I need to make to the DisableMyEnvironment
macro in the MWE below so as to achieve the equivalent of globalrenewenvironment
?
Currently, the MWE yields:
Once this is working as desired, the second line in blue should be in black.
Notes:
- There are two test cases. The default one is within a
foreach
and commenting outdefForeachTestCase
uses a simple group.
References:
globalrenewcommand equivalent of globaldef.
Code:
defForeachTestCase%
documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%
else
begingroup
DisableMyEnvironment
endgroup
fi
medskippar
MyTestTextblack
enddocument
macros environments grouping
I need to execute a renewenvironment
within a group. Using globalrenewenvironment
is not sufficient.
What changes do I need to make to the DisableMyEnvironment
macro in the MWE below so as to achieve the equivalent of globalrenewenvironment
?
Currently, the MWE yields:
Once this is working as desired, the second line in blue should be in black.
Notes:
- There are two test cases. The default one is within a
foreach
and commenting outdefForeachTestCase
uses a simple group.
References:
globalrenewcommand equivalent of globaldef.
Code:
defForeachTestCase%
documentclassarticle
usepackagexcolor
usepackagexstring
usepackagetikz
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
renewenvironmentMyEnvironment[1]%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
ifdefinedForeachTestCase
foreach x in 1,...,3 %
IfStrEqCasex%
1%
2DisableMyEnvironment%
3%
%
else
begingroup
DisableMyEnvironment
endgroup
fi
medskippar
MyTestTextblack
enddocument
macros environments grouping
macros environments grouping
edited Aug 28 at 19:22
asked Aug 28 at 18:38
Peter Grill
161k24427733
161k24427733
I don't know your real application, but one option is to useaftergroupDisableMyEnvironment
. I don't know if this will do what you want, though.
â Phelype Oleinik
Aug 28 at 18:47
@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within afpreach
). Will look into it and try to figure it out.
â Peter Grill
Aug 28 at 18:50
I read somewhere that aforeach
does its thing inside two grouping levels, soaftergroupaftergroupaftergroupDisableMyEnvironment
should do. Not the prettiest code there is though :P
â Phelype Oleinik
Aug 28 at 18:52
@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both theenvironement
andendenvironment
separately.
â Peter Grill
Aug 28 at 19:16
It's a bit hacky, but would work:letdefgdefrenewenvironmentMyEnvironment[1]
and it's global!
â Andreas Storvik Strauman
Aug 28 at 19:29
 |Â
show 1 more comment
I don't know your real application, but one option is to useaftergroupDisableMyEnvironment
. I don't know if this will do what you want, though.
â Phelype Oleinik
Aug 28 at 18:47
@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within afpreach
). Will look into it and try to figure it out.
â Peter Grill
Aug 28 at 18:50
I read somewhere that aforeach
does its thing inside two grouping levels, soaftergroupaftergroupaftergroupDisableMyEnvironment
should do. Not the prettiest code there is though :P
â Phelype Oleinik
Aug 28 at 18:52
@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both theenvironement
andendenvironment
separately.
â Peter Grill
Aug 28 at 19:16
It's a bit hacky, but would work:letdefgdefrenewenvironmentMyEnvironment[1]
and it's global!
â Andreas Storvik Strauman
Aug 28 at 19:29
I don't know your real application, but one option is to use
aftergroupDisableMyEnvironment
. I don't know if this will do what you want, though.â Phelype Oleinik
Aug 28 at 18:47
I don't know your real application, but one option is to use
aftergroupDisableMyEnvironment
. I don't know if this will do what you want, though.â Phelype Oleinik
Aug 28 at 18:47
@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a
fpreach
). Will look into it and try to figure it out.â Peter Grill
Aug 28 at 18:50
@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a
fpreach
). Will look into it and try to figure it out.â Peter Grill
Aug 28 at 18:50
I read somewhere that a
foreach
does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment
should do. Not the prettiest code there is though :Pâ Phelype Oleinik
Aug 28 at 18:52
I read somewhere that a
foreach
does its thing inside two grouping levels, so aftergroupaftergroupaftergroupDisableMyEnvironment
should do. Not the prettiest code there is though :Pâ Phelype Oleinik
Aug 28 at 18:52
@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the
environement
and endenvironment
separately.â Peter Grill
Aug 28 at 19:16
@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the
environement
and endenvironment
separately.â Peter Grill
Aug 28 at 19:16
It's a bit hacky, but would work:
letdefgdefrenewenvironmentMyEnvironment[1]
and it's global!â Andreas Storvik Strauman
Aug 28 at 19:29
It's a bit hacky, but would work:
letdefgdefrenewenvironmentMyEnvironment[1]
and it's global!â Andreas Storvik Strauman
Aug 28 at 19:29
 |Â
show 1 more comment
3 Answers
3
active
oldest
votes
up vote
5
down vote
accepted
Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment
, and then in the DisableMyEnvironment
macro, globally reassign by way of
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
MWE:
documentclassarticle
usepackagexcolor
newenvironmentXEnvironment[1]%
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
begingroup
DisableMyEnvironment
endgroup
medskippar
MyTestTextblack
enddocument
Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the newforeach
case.
â Peter Grill
Aug 28 at 19:27
@PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
â Steven B. Segletes
Aug 28 at 19:46
1
Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
â Peter Grill
Aug 28 at 20:56
add a comment |Â
up vote
3
down vote
Edit: First approach didn't seem to work with optional arguments.
Edit 2: Found an easier way using globaldefs
:
Final answer:
In spirit of answering how to do a renewenvironment
global:
documentclassarticle
begindocument
newenvironmenttestHELLOWORLD
bgroup
globaldefs=1
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
Second answer:
Two commands loosely inspired by makeatletter
and makeatother
: makerenewglobal
and makerenewlocal
. When makerenewglobal
is called, renewenvironment
do only global definitions. If makerenewlocal
is called, it does the oposite: makes all renewenvironment
-definitions local.
documentclassarticle
makeatletter
let@local@newenv@newenv
longdef@global@newenv#1#2#3#4%
@ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
l@ngrel@xexpandaftergdefcsname end#1endcsname#4%
gdefmakerenewglobalgloballet@newenv@global@newenv
gdefmakerenewlocalgloballet@newenv@local@newenv
begindocument
newenvironmenttestHELLOWORLD
bgroupmakerenewglobal
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
First answer:
In spirit of semi-generality; a command, makeenvglobaltheenv
, that makes a environment global:
documentclassarticle
gdefmakeenvglobal#1%
globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname
begindocument
newenvironmenttestHELLOWORLD
bgroup
renewenvironmenttestfoobar
makeenvglobaltest
egroup
begintest
endtest
enddocument
prints foo bar
Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
â Peter Grill
Aug 28 at 19:17
@PeterGrill Oh. Yeah somethings going on. Give me a minute!
â Andreas Storvik Strauman
Aug 28 at 19:22
@PeterGrill See new answer!
â Andreas Storvik Strauman
Aug 28 at 19:40
Yep, revised answer works.
â Peter Grill
Aug 28 at 21:00
add a comment |Â
up vote
1
down vote
As requested :)
I read somewhere here that foreach
executes its commands inside two groups. You can check this statement with this (requires e-TeX):
documentclassarticle
usepackagepgffor
begindocument
foreach i in 0thecurrentgrouplevel
enddocument
which will print 2
:)
If you want to do a definition outside the scope of this foreach
, then you can use a couple of aftergroup
s. In your case you want to run DisableMyEnvironment
(one token) outside of two grouping levels.
If you do aftergroupDisableMyEnvironment
, this will insert DisableMyEnvironment
after the first group (one aftergroup
per token). To make it reach the second level, you have to aftergroup
that (two tokens), so aftergroupaftergroup
aftergroupDisableMyEnvironment
.
Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.
Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroup
s, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter
=D
I made a (probably suboptimal) macro afterNgroups<N><token-list>
that inserts the <token-list>
after <N>
groups:
makeatletter
defafterNgroups#1#2%
count@z@
toks@#2%
loop
ifnumcount@<#1 %
toks2%
expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
toks2
expandafterexpandafterexpandafter
expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
toks@expandafterthetoks2%
advancecount@@ne
repeat
thetoks@
makeatother
you can use this macro for your case with afterNgroups2DisableMyEnvironment
. It apparently works for trivial cases. Didn't test it extensively though.
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment
, and then in the DisableMyEnvironment
macro, globally reassign by way of
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
MWE:
documentclassarticle
usepackagexcolor
newenvironmentXEnvironment[1]%
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
begingroup
DisableMyEnvironment
endgroup
medskippar
MyTestTextblack
enddocument
Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the newforeach
case.
â Peter Grill
Aug 28 at 19:27
@PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
â Steven B. Segletes
Aug 28 at 19:46
1
Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
â Peter Grill
Aug 28 at 20:56
add a comment |Â
up vote
5
down vote
accepted
Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment
, and then in the DisableMyEnvironment
macro, globally reassign by way of
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
MWE:
documentclassarticle
usepackagexcolor
newenvironmentXEnvironment[1]%
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
begingroup
DisableMyEnvironment
endgroup
medskippar
MyTestTextblack
enddocument
Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the newforeach
case.
â Peter Grill
Aug 28 at 19:27
@PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
â Steven B. Segletes
Aug 28 at 19:46
1
Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
â Peter Grill
Aug 28 at 20:56
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment
, and then in the DisableMyEnvironment
macro, globally reassign by way of
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
MWE:
documentclassarticle
usepackagexcolor
newenvironmentXEnvironment[1]%
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
begingroup
DisableMyEnvironment
endgroup
medskippar
MyTestTextblack
enddocument
Create a dummy (or alternate) environment in the global scope (preamble), here, XEnvironment
, and then in the DisableMyEnvironment
macro, globally reassign by way of
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
MWE:
documentclassarticle
usepackagexcolor
newenvironmentXEnvironment[1]%
newenvironmentMyEnvironment[1][blue]%
begingroup
color#1%
%
endgroup
%
newcommand*DisableMyEnvironment%
%% How make this global??
globalletMyEnvironmentXEnvironment%
globalletendMyEnvironmentendXEnvironment%
%
newcommand*MyTestText[1]%
Some before text
beginMyEnvironment
This should be in #1.
endMyEnvironment
Some after text%
begindocument
MyTestTextblue
%DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
begingroup
DisableMyEnvironment
endgroup
medskippar
MyTestTextblack
enddocument
answered Aug 28 at 18:59
Steven B. Segletes
147k9186389
147k9186389
Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the newforeach
case.
â Peter Grill
Aug 28 at 19:27
@PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
â Steven B. Segletes
Aug 28 at 19:46
1
Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
â Peter Grill
Aug 28 at 20:56
add a comment |Â
Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the newforeach
case.
â Peter Grill
Aug 28 at 19:27
@PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
â Steven B. Segletes
Aug 28 at 19:46
1
Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
â Peter Grill
Aug 28 at 20:56
Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new
foreach
case.â Peter Grill
Aug 28 at 19:27
Thanks. I was initially opposed to using two separate commands to disable and define a new dummy environment, but then this does seem simpler to use as then you don't have to worry about which grouping level you are in (works fine for both the original text case and the new
foreach
case.â Peter Grill
Aug 28 at 19:27
@PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
â Steven B. Segletes
Aug 28 at 19:46
@PeterGrill I am not sure why using 2 commands should be an issue. For example, to use a changed catcode in a macro, the catcode has to be changed prior to the macro definition, so that it takes effect when the macro's argument gets tokenized. While cumbersome, nobody really complains that the catcode change should occur inside the macro definition. In summary, it's all in the preamble...it's not like you have to define things on the fly.
â Steven B. Segletes
Aug 28 at 19:46
1
1
Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
â Peter Grill
Aug 28 at 20:56
Agreed. I attempted to say that with the "initially".. Hiding it in the preamble is perfectly fine.
â Peter Grill
Aug 28 at 20:56
add a comment |Â
up vote
3
down vote
Edit: First approach didn't seem to work with optional arguments.
Edit 2: Found an easier way using globaldefs
:
Final answer:
In spirit of answering how to do a renewenvironment
global:
documentclassarticle
begindocument
newenvironmenttestHELLOWORLD
bgroup
globaldefs=1
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
Second answer:
Two commands loosely inspired by makeatletter
and makeatother
: makerenewglobal
and makerenewlocal
. When makerenewglobal
is called, renewenvironment
do only global definitions. If makerenewlocal
is called, it does the oposite: makes all renewenvironment
-definitions local.
documentclassarticle
makeatletter
let@local@newenv@newenv
longdef@global@newenv#1#2#3#4%
@ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
l@ngrel@xexpandaftergdefcsname end#1endcsname#4%
gdefmakerenewglobalgloballet@newenv@global@newenv
gdefmakerenewlocalgloballet@newenv@local@newenv
begindocument
newenvironmenttestHELLOWORLD
bgroupmakerenewglobal
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
First answer:
In spirit of semi-generality; a command, makeenvglobaltheenv
, that makes a environment global:
documentclassarticle
gdefmakeenvglobal#1%
globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname
begindocument
newenvironmenttestHELLOWORLD
bgroup
renewenvironmenttestfoobar
makeenvglobaltest
egroup
begintest
endtest
enddocument
prints foo bar
Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
â Peter Grill
Aug 28 at 19:17
@PeterGrill Oh. Yeah somethings going on. Give me a minute!
â Andreas Storvik Strauman
Aug 28 at 19:22
@PeterGrill See new answer!
â Andreas Storvik Strauman
Aug 28 at 19:40
Yep, revised answer works.
â Peter Grill
Aug 28 at 21:00
add a comment |Â
up vote
3
down vote
Edit: First approach didn't seem to work with optional arguments.
Edit 2: Found an easier way using globaldefs
:
Final answer:
In spirit of answering how to do a renewenvironment
global:
documentclassarticle
begindocument
newenvironmenttestHELLOWORLD
bgroup
globaldefs=1
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
Second answer:
Two commands loosely inspired by makeatletter
and makeatother
: makerenewglobal
and makerenewlocal
. When makerenewglobal
is called, renewenvironment
do only global definitions. If makerenewlocal
is called, it does the oposite: makes all renewenvironment
-definitions local.
documentclassarticle
makeatletter
let@local@newenv@newenv
longdef@global@newenv#1#2#3#4%
@ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
l@ngrel@xexpandaftergdefcsname end#1endcsname#4%
gdefmakerenewglobalgloballet@newenv@global@newenv
gdefmakerenewlocalgloballet@newenv@local@newenv
begindocument
newenvironmenttestHELLOWORLD
bgroupmakerenewglobal
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
First answer:
In spirit of semi-generality; a command, makeenvglobaltheenv
, that makes a environment global:
documentclassarticle
gdefmakeenvglobal#1%
globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname
begindocument
newenvironmenttestHELLOWORLD
bgroup
renewenvironmenttestfoobar
makeenvglobaltest
egroup
begintest
endtest
enddocument
prints foo bar
Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
â Peter Grill
Aug 28 at 19:17
@PeterGrill Oh. Yeah somethings going on. Give me a minute!
â Andreas Storvik Strauman
Aug 28 at 19:22
@PeterGrill See new answer!
â Andreas Storvik Strauman
Aug 28 at 19:40
Yep, revised answer works.
â Peter Grill
Aug 28 at 21:00
add a comment |Â
up vote
3
down vote
up vote
3
down vote
Edit: First approach didn't seem to work with optional arguments.
Edit 2: Found an easier way using globaldefs
:
Final answer:
In spirit of answering how to do a renewenvironment
global:
documentclassarticle
begindocument
newenvironmenttestHELLOWORLD
bgroup
globaldefs=1
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
Second answer:
Two commands loosely inspired by makeatletter
and makeatother
: makerenewglobal
and makerenewlocal
. When makerenewglobal
is called, renewenvironment
do only global definitions. If makerenewlocal
is called, it does the oposite: makes all renewenvironment
-definitions local.
documentclassarticle
makeatletter
let@local@newenv@newenv
longdef@global@newenv#1#2#3#4%
@ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
l@ngrel@xexpandaftergdefcsname end#1endcsname#4%
gdefmakerenewglobalgloballet@newenv@global@newenv
gdefmakerenewlocalgloballet@newenv@local@newenv
begindocument
newenvironmenttestHELLOWORLD
bgroupmakerenewglobal
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
First answer:
In spirit of semi-generality; a command, makeenvglobaltheenv
, that makes a environment global:
documentclassarticle
gdefmakeenvglobal#1%
globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname
begindocument
newenvironmenttestHELLOWORLD
bgroup
renewenvironmenttestfoobar
makeenvglobaltest
egroup
begintest
endtest
enddocument
prints foo bar
Edit: First approach didn't seem to work with optional arguments.
Edit 2: Found an easier way using globaldefs
:
Final answer:
In spirit of answering how to do a renewenvironment
global:
documentclassarticle
begindocument
newenvironmenttestHELLOWORLD
bgroup
globaldefs=1
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
Second answer:
Two commands loosely inspired by makeatletter
and makeatother
: makerenewglobal
and makerenewlocal
. When makerenewglobal
is called, renewenvironment
do only global definitions. If makerenewlocal
is called, it does the oposite: makes all renewenvironment
-definitions local.
documentclassarticle
makeatletter
let@local@newenv@newenv
longdef@global@newenv#1#2#3#4%
@ifundefined#1globalexpandafterletcsname#1expandafterendcsnamecsname end#1endcsnamerelax
letdefgdefexpandafternew@commandcsname #1endcsname#2#3%
l@ngrel@xexpandaftergdefcsname end#1endcsname#4%
gdefmakerenewglobalgloballet@newenv@global@newenv
gdefmakerenewlocalgloballet@newenv@local@newenv
begindocument
newenvironmenttestHELLOWORLD
bgroupmakerenewglobal
renewenvironmenttest[1][world]foo #1bar
egroup
begintest[hello]
endtest
enddocument
First answer:
In spirit of semi-generality; a command, makeenvglobaltheenv
, that makes a environment global:
documentclassarticle
gdefmakeenvglobal#1%
globalexpandafterexpandafterletcsname #1expandafterendcsnamecsname #1endcsname
globalexpandafterexpandafterletcsname end#1expandafterendcsnamecsname end#1endcsname
begindocument
newenvironmenttestHELLOWORLD
bgroup
renewenvironmenttestfoobar
makeenvglobaltest
egroup
begintest
endtest
enddocument
prints foo bar
edited Aug 28 at 20:01
answered Aug 28 at 19:08
Andreas Storvik Strauman
2,267418
2,267418
Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
â Peter Grill
Aug 28 at 19:17
@PeterGrill Oh. Yeah somethings going on. Give me a minute!
â Andreas Storvik Strauman
Aug 28 at 19:22
@PeterGrill See new answer!
â Andreas Storvik Strauman
Aug 28 at 19:40
Yep, revised answer works.
â Peter Grill
Aug 28 at 21:00
add a comment |Â
Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
â Peter Grill
Aug 28 at 19:17
@PeterGrill Oh. Yeah somethings going on. Give me a minute!
â Andreas Storvik Strauman
Aug 28 at 19:22
@PeterGrill See new answer!
â Andreas Storvik Strauman
Aug 28 at 19:40
Yep, revised answer works.
â Peter Grill
Aug 28 at 21:00
Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
â Peter Grill
Aug 28 at 19:17
Does this need to be altered to handle the case where the environment having an optional parameter (as in the MWE)?
â Peter Grill
Aug 28 at 19:17
@PeterGrill Oh. Yeah somethings going on. Give me a minute!
â Andreas Storvik Strauman
Aug 28 at 19:22
@PeterGrill Oh. Yeah somethings going on. Give me a minute!
â Andreas Storvik Strauman
Aug 28 at 19:22
@PeterGrill See new answer!
â Andreas Storvik Strauman
Aug 28 at 19:40
@PeterGrill See new answer!
â Andreas Storvik Strauman
Aug 28 at 19:40
Yep, revised answer works.
â Peter Grill
Aug 28 at 21:00
Yep, revised answer works.
â Peter Grill
Aug 28 at 21:00
add a comment |Â
up vote
1
down vote
As requested :)
I read somewhere here that foreach
executes its commands inside two groups. You can check this statement with this (requires e-TeX):
documentclassarticle
usepackagepgffor
begindocument
foreach i in 0thecurrentgrouplevel
enddocument
which will print 2
:)
If you want to do a definition outside the scope of this foreach
, then you can use a couple of aftergroup
s. In your case you want to run DisableMyEnvironment
(one token) outside of two grouping levels.
If you do aftergroupDisableMyEnvironment
, this will insert DisableMyEnvironment
after the first group (one aftergroup
per token). To make it reach the second level, you have to aftergroup
that (two tokens), so aftergroupaftergroup
aftergroupDisableMyEnvironment
.
Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.
Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroup
s, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter
=D
I made a (probably suboptimal) macro afterNgroups<N><token-list>
that inserts the <token-list>
after <N>
groups:
makeatletter
defafterNgroups#1#2%
count@z@
toks@#2%
loop
ifnumcount@<#1 %
toks2%
expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
toks2
expandafterexpandafterexpandafter
expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
toks@expandafterthetoks2%
advancecount@@ne
repeat
thetoks@
makeatother
you can use this macro for your case with afterNgroups2DisableMyEnvironment
. It apparently works for trivial cases. Didn't test it extensively though.
add a comment |Â
up vote
1
down vote
As requested :)
I read somewhere here that foreach
executes its commands inside two groups. You can check this statement with this (requires e-TeX):
documentclassarticle
usepackagepgffor
begindocument
foreach i in 0thecurrentgrouplevel
enddocument
which will print 2
:)
If you want to do a definition outside the scope of this foreach
, then you can use a couple of aftergroup
s. In your case you want to run DisableMyEnvironment
(one token) outside of two grouping levels.
If you do aftergroupDisableMyEnvironment
, this will insert DisableMyEnvironment
after the first group (one aftergroup
per token). To make it reach the second level, you have to aftergroup
that (two tokens), so aftergroupaftergroup
aftergroupDisableMyEnvironment
.
Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.
Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroup
s, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter
=D
I made a (probably suboptimal) macro afterNgroups<N><token-list>
that inserts the <token-list>
after <N>
groups:
makeatletter
defafterNgroups#1#2%
count@z@
toks@#2%
loop
ifnumcount@<#1 %
toks2%
expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
toks2
expandafterexpandafterexpandafter
expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
toks@expandafterthetoks2%
advancecount@@ne
repeat
thetoks@
makeatother
you can use this macro for your case with afterNgroups2DisableMyEnvironment
. It apparently works for trivial cases. Didn't test it extensively though.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
As requested :)
I read somewhere here that foreach
executes its commands inside two groups. You can check this statement with this (requires e-TeX):
documentclassarticle
usepackagepgffor
begindocument
foreach i in 0thecurrentgrouplevel
enddocument
which will print 2
:)
If you want to do a definition outside the scope of this foreach
, then you can use a couple of aftergroup
s. In your case you want to run DisableMyEnvironment
(one token) outside of two grouping levels.
If you do aftergroupDisableMyEnvironment
, this will insert DisableMyEnvironment
after the first group (one aftergroup
per token). To make it reach the second level, you have to aftergroup
that (two tokens), so aftergroupaftergroup
aftergroupDisableMyEnvironment
.
Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.
Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroup
s, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter
=D
I made a (probably suboptimal) macro afterNgroups<N><token-list>
that inserts the <token-list>
after <N>
groups:
makeatletter
defafterNgroups#1#2%
count@z@
toks@#2%
loop
ifnumcount@<#1 %
toks2%
expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
toks2
expandafterexpandafterexpandafter
expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
toks@expandafterthetoks2%
advancecount@@ne
repeat
thetoks@
makeatother
you can use this macro for your case with afterNgroups2DisableMyEnvironment
. It apparently works for trivial cases. Didn't test it extensively though.
As requested :)
I read somewhere here that foreach
executes its commands inside two groups. You can check this statement with this (requires e-TeX):
documentclassarticle
usepackagepgffor
begindocument
foreach i in 0thecurrentgrouplevel
enddocument
which will print 2
:)
If you want to do a definition outside the scope of this foreach
, then you can use a couple of aftergroup
s. In your case you want to run DisableMyEnvironment
(one token) outside of two grouping levels.
If you do aftergroupDisableMyEnvironment
, this will insert DisableMyEnvironment
after the first group (one aftergroup
per token). To make it reach the second level, you have to aftergroup
that (two tokens), so aftergroupaftergroup
aftergroupDisableMyEnvironment
.
Have in mind that this is not a global assignment, rather just local to another grouping level. If you are in, say, a third grouping level, the changes will be restored after the third one ends.
Just a few days ago I was doing something (can't remember what though --- or can I?) and was using a very long chain of aftergroup
s, and was getting it wrong because I was missing one or another. What did I do? An even longer chain of expandafter
=D
I made a (probably suboptimal) macro afterNgroups<N><token-list>
that inserts the <token-list>
after <N>
groups:
makeatletter
defafterNgroups#1#2%
count@z@
toks@#2%
loop
ifnumcount@<#1 %
toks2%
expandafter@tforexpandaftertknexpandafter:expandafter=thetoks@do%
toks2
expandafterexpandafterexpandafter
expandaftertheexpandaftertoksexpandafter2expandafteraftergrouptkn%
toks@expandafterthetoks2%
advancecount@@ne
repeat
thetoks@
makeatother
you can use this macro for your case with afterNgroups2DisableMyEnvironment
. It apparently works for trivial cases. Didn't test it extensively though.
edited Aug 29 at 11:11
answered Aug 28 at 23:10
Phelype Oleinik
16.9k33769
16.9k33769
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f448212%2fhow-to-perform-a-global-renewenvironment%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
I don't know your real application, but one option is to use
aftergroupDisableMyEnvironment
. I don't know if this will do what you want, though.â Phelype Oleinik
Aug 28 at 18:47
@PhelypeOleinik: Yep, that works fine in the MWE. It doesn't seem to work in my actual use case (which is within a
fpreach
). Will look into it and try to figure it out.â Peter Grill
Aug 28 at 18:50
I read somewhere that a
foreach
does its thing inside two grouping levels, soaftergroupaftergroupaftergroupDisableMyEnvironment
should do. Not the prettiest code there is though :Pâ Phelype Oleinik
Aug 28 at 18:52
@PhelypeOleinik: Yep that was it. Thanks. You should post an answer as that seems to be the cleanest approach and does not require dealing with both the
environement
andendenvironment
separately.â Peter Grill
Aug 28 at 19:16
It's a bit hacky, but would work:
letdefgdefrenewenvironmentMyEnvironment[1]
and it's global!â Andreas Storvik Strauman
Aug 28 at 19:29